//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Text;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Eas.WebCrawler.Interfaces;
using Eas.WebCrawler.Model;
using Eas.WebCrawler.Model.Core;

namespace Eas.WebCrawler.Test.Model {
    /// <summary>
    /// Summary description for ErrorTests
    /// </summary>
    [TestClass]
    public class ErrorTests {
        public ErrorTests() {

        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //

        NMock2.Mockery _Mockery;

        // Use TestInitialize to run code before running each test 
        [TestInitialize()]
        public void MyTestInitialize() {
            _Mockery = new NMock2.Mockery();
        }

        //
        // Use TestCleanup to run code after each test has run
        [TestCleanup()]
        public void MyTestCleanup() {
            _Mockery.VerifyAllExpectationsHaveBeenMet();
            _Mockery.Dispose();
        }

        //
        #endregion

        [ExpectedException(typeof(WebFailureException))]
        [TestMethod]
        /// <summary>Executes the GetRequestError test.</summary>
        public void GetRequestError() {
            BaseProcessingState state;
            WorkerContext _context;
            TestSettings settings = new TestSettings();
            Eas.WebCrawler.Model.Events.BaseWebCrawlerEvents events = new Eas.WebCrawler.Model.Events.BaseWebCrawlerEvents();
            Eas.WebCrawler.Model.Gateway.BaseWebGateway gateway = new Eas.WebCrawler.Model.Gateway.BaseWebGateway();
            Eas.WebCrawler.Interfaces.RequestStore store = _Mockery.NewMock<Eas.WebCrawler.Interfaces.RequestStore>();
            Eas.WebCrawler.Model.StateTrackers.BaseStateTracker stateTracker = new Eas.WebCrawler.Model.StateTrackers.BaseStateTracker();
            NMock2.Expect.Once.On(store).Method("Initialize").WithAnyArguments();
            Initialize(out _context, out state, settings, store, events, gateway, stateTracker);

            using (WorkerContext context = _context) {
                DoUnstartedToGetRequest(state, events, context);
                NMock2.Expect.Once.On(store).Method("PopRequest").Will(NMock2.Throw.Exception(new WebFailureException("aa", 500, null)));
                DoGetRequestToGetResponse(state, context);
            }
        }

        private void DoUnstartedToGetRequest(BaseProcessingState state, Eas.WebCrawler.Model.Events.BaseWebCrawlerEvents events, WorkerContext context) {
            events.Fire_Starting();
            context.StateTracker.RequestChange(WorkerState.Working);
            StepForward(state, context);
            VerifyAction(typeof(Eas.WebCrawler.Model.Actions.GetRequestAction), state);
        }

        private void DoGetRequestToGetResponse(BaseProcessingState state, WorkerContext context) {
            StepForward(state, context);
            VerifyAction(typeof(Eas.WebCrawler.Model.Actions.GetResponseAction), state);
        }

        private void Initialize(out WorkerContext context, out BaseProcessingState state, Eas.WebCrawler.Test.Model.TestSettings settings, Eas.WebCrawler.Interfaces.RequestStore store, Eas.WebCrawler.Model.Events.BaseWebCrawlerEvents events, Eas.WebCrawler.Model.Gateway.WebGateway gateway, Eas.WebCrawler.Model.StateTrackers.BaseStateTracker stateTracker) {
            settings.SleepTimeInMilliseconds = 1;
            context = new WorkerContext(new BaseWebCrawlerContext(settings, store, events), new Eas.WebCrawler.Model.Actions.BaseActionFactory(), events, gateway, events, stateTracker);
            state = context.StateTracker[0];
        }


        private void VerifyStopped(BaseProcessingState state, WorkerContext context) {
            VerifyAction(typeof(Eas.WebCrawler.Model.Actions.TerminalAction), state);
            Assert.IsNull(state.Action.BeginAction(context, state, null));
            //Assert.IsTrue(state.WasTerminated);
        }

        private void VerifyAction(Type type, BaseProcessingState state) {
            Assert.IsInstanceOfType(state.Action, type);
        }

        private void StepForward(BaseProcessingState state, WorkerContext context) {
            context.StateTracker.LoadChangeRequestsIntoState(state);
            IAsyncResult result = state.Action.BeginAction(context, state, null);
            BaseProcessingState.TransitionToNextState(state, context, result);
        }
    }
}
